home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Extra 1997 #2 / Amiga Plus Extra 1997 #2.iso / pd / misc / golded / api / rexx / main.c next >
Encoding:
C/C++ Source or Header  |  1997-02-16  |  10.3 KB  |  376 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  GoldED API client example code, ©1995 Dietmar Eilert. Dice:
  4.  
  5.  dcc main.c -// -mRR -r -proto -2.0 -o ram:rexx
  6.  
  7.  The following code demonstrates how to  add  additional  internal  commands  to
  8.  GoldED  using  a  client. After having installed this client using GoldED's API
  9.  requester you may use the following additional commands within menus, macros or
  10.  in the command requester:
  11.  
  12.     o DISPLAYBEEP (flash screen)
  13.     o ABOUT
  14.  
  15.  The following  example  uses  synchronous  ARexx  communication:  Requests  are
  16.  PutMsg()'ed  to  GoldED's  port,  followed  by a WaitPort() to get the editor's
  17.  response. This works fine since we need no ARexx communication  after  the  API
  18.  link has been established. If there were ARexx communication AFTER the link has
  19.  been established (i.e. after sending the 'API  PORT=...'  command  to  register
  20.  with  GoldED),  we  would  have to use an asynchronous design beeing capable of
  21.  answering incoming API messages while waiting for completion of ARexx  requests
  22.  sent to GoldED.
  23.  
  24.   ------------------------------------------------------------------------------
  25. */
  26.  
  27. /// "includes"
  28.  
  29. #define Prototype extern
  30.  
  31. #include <exec/exec.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <dos/dos.h>
  36. #include <dos/rdargs.h>
  37. #include <intuition/intuition.h>
  38. #include <rexx/errors.h>
  39. #include <rexx/rxslib.h>
  40. #include <utility/tagitem.h>
  41. #include <clib/exec_protos.h>
  42. #include <clib/dos_protos.h>
  43. #include <clib/intuition_protos.h>
  44. #include <clib/rexxsyslib_protos.h>
  45.  
  46. #include "golded:api/include/golded.h"
  47.  
  48. Prototype void   main(int, char **);
  49. Prototype void   HandleAPI(char *);
  50. Prototype void   Dispatch(struct APIMessage *);
  51. Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
  52. Prototype LONG   CommandBeep (ULONG *, struct APIMessage *);
  53. Prototype LONG   CommandAbout(ULONG *, struct APIMessage *);
  54.  
  55. ///
  56. /// "main"
  57.  
  58. void
  59. main(int argc, char **argv)
  60. {
  61.     const char *version = "$VER: rexx 1.5 (" __COMMODORE_DATE__ ")";
  62.  
  63.     if (argc == 2)
  64.         HandleAPI(argv[1] + 5);
  65.     else
  66.         puts("syntax error: rexx HOST=<host>");
  67.  
  68.     exit(0);
  69. }
  70.  
  71. ///
  72. /// "API management"
  73.  
  74. /* --------------------------------- HandleAPI ---------------------------------
  75.  
  76.  Register with GoldED & handle incoming API messages.
  77.  
  78. */
  79.  
  80. void
  81. HandleAPI(host)
  82.  
  83. char *host;
  84. {
  85.     struct MsgPort *replyPort;
  86.  
  87.     if (replyPort = CreateMsgPort()) {
  88.  
  89.         char   command[255];
  90.         ULONG *result;
  91.  
  92.         sprintf(command, "API PORT=%ld CLASS=%ld", replyPort, API_CLASS_ROOT | API_CLASS_REXX);
  93.  
  94.         if (result = SendRexxCommand(host, command, replyPort, NULL)) {
  95.  
  96.             if (*result == RC_OK) {
  97.  
  98.                 BOOL active = TRUE;
  99.  
  100.                 do {
  101.  
  102.                     struct APIMessage *apiMsg, *nextMsg;
  103.  
  104.                     // API messages might already have arrived since SendRexxCommand() only pulls one message of the port
  105.  
  106.                     while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
  107.                         WaitPort(replyPort);
  108.  
  109.                     do {
  110.  
  111.                         for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
  112.  
  113.                             if (nextMsg->api_State == API_STATE_NOTIFY) {
  114.  
  115.                                 switch (nextMsg->api_Class) {
  116.  
  117.                                     case API_CLASS_ROOT:
  118.  
  119.                                         switch (nextMsg->api_Action) {
  120.  
  121.                                             case API_ACTION_DIE:
  122.  
  123.                                                 active = FALSE;
  124.                                                 break;
  125.  
  126.                                             case API_ACTION_INTRODUCE:
  127.  
  128.                                                 static struct TagItem tags[] = {
  129.  
  130.                                                     API_Client_Name,      "rexx",
  131.                                                     API_Client_Copyright, "©1995 Dietmar Eilert",
  132.                                                     API_Client_Purpose,   "API client example code",
  133.                                                     API_Client_Template,  "DISPLAYBEEP",
  134.                                                     API_Client_Template,  "ABOUT",
  135.                                                     TAG_DONE
  136.                                                 };
  137.  
  138.                                                 nextMsg->api_Data = tags;
  139.                                                 break;
  140.  
  141.                                             default:
  142.  
  143.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  144.                                         }
  145.  
  146.                                         break;
  147.  
  148.                                     case API_CLASS_REXX:
  149.  
  150.                                         switch (nextMsg->api_Action) {
  151.  
  152.                                             case API_ACTION_COMMAND:
  153.  
  154.                                                 Dispatch(nextMsg);
  155.                                                 break;
  156.  
  157.                                             default:
  158.  
  159.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  160.                                         }
  161.                                         break;
  162.  
  163.                                     default:
  164.  
  165.                                         nextMsg->api_Error = API_ERROR_UNKNOWN;
  166.                                 }
  167.                             }
  168.                         }
  169.  
  170.                         ReplyMsg((struct Message *)apiMsg);
  171.  
  172.                     } while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
  173.  
  174.                 } while (active);
  175.             }
  176.         }
  177.  
  178.         DeleteMsgPort(replyPort);
  179.     }
  180. }
  181.  
  182.  
  183. ///
  184. /// "dispatcher"
  185.  
  186. /* --------------------------------- Dispatch ----------------------------------
  187.  
  188.  Dispatch incoming command: examine command string (command part is uppercase
  189.  already), look for handler function related to command, parse arguments (if 
  190.  command supports arguments), call handler.
  191.  
  192. */
  193.  
  194. void
  195. Dispatch(apiMsg)
  196.  
  197. struct APIMessage *apiMsg;
  198. {
  199.     struct RDArgs *rdArgs, *args;
  200.  
  201.     if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
  202.  
  203.         static char buffer[1024];
  204.  
  205.         // table of supported commands, associated handlers & template strings
  206.  
  207.         static struct parser { char *command; LONG (*handler)(ULONG *, struct APIMessage *); char *template; } parser[] = {
  208.  
  209.             "DISPLAYBEEP",  (APTR)CommandBeep,  NULL,
  210.             "ABOUT",        (APTR)CommandAbout, NULL,
  211.              NULL
  212.         };
  213.  
  214.         ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  215.  
  216.         struct APIRexxNotify *notify = (struct APIRexxNotify *)apiMsg->api_Data;
  217.  
  218.         // make LF-terminated copy of command string (required by dos/readArgs):
  219.  
  220.         strcpy(buffer, notify->arn_Command);
  221.         strcat(buffer, "\12");
  222.  
  223.         for (n = 0; parser[n].command; ++n) {
  224.  
  225.             if (!memcmp(buffer, parser[n].command, strlen(parser[n].command))) {
  226.  
  227.                 // tell GoldED that message has been consumed by us:
  228.  
  229.                 apiMsg->api_State = API_STATE_CONSUMED;
  230.  
  231.                 char *arguments = buffer + strlen(parser[n].command);
  232.  
  233.                 rdArgs->RDA_Source.CS_Buffer = arguments;
  234.                 rdArgs->RDA_Source.CS_Length = strlen(arguments);
  235.                 rdArgs->RDA_Source.CS_CurChr = 0;
  236.                 rdArgs->RDA_DAList           = NULL;
  237.                 rdArgs->RDA_Buffer           = NULL;
  238.  
  239.                 if (parser[n].template) {
  240.  
  241.                     if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
  242.  
  243.                         notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
  244.  
  245.                         FreeArgs(args);
  246.                     }
  247.                     else {
  248.  
  249.                         static char errorText[81];
  250.  
  251.                         notify->arn_RC           = RC_WARN;
  252.                         notify->arn_CommandError = errorText;
  253.  
  254.                         Fault(IoErr(), "IoErr()", errorText, 80);
  255.                     }
  256.                 }
  257.                 else
  258.                     notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
  259.             }
  260.         }
  261.  
  262.         FreeDosObject(DOS_RDARGS, rdArgs);
  263.     }
  264. }
  265.  
  266. /* -------------------------------- CommandBeep --------------------------------
  267.  
  268.  DISPLAYBEEP
  269.  
  270. */
  271.  
  272. LONG
  273. CommandBeep(argArray, apiMsg)
  274.  
  275. ULONG  *argArray;
  276. struct APIMessage *apiMsg;
  277. {
  278.     DisplayBeep(0);
  279.  
  280.     return(RC_OK);
  281. }
  282.  
  283. /* ------------------------------- CommandAbout --------------------------------
  284.  
  285.  ABOUT (open a requester on GoldED's screen)
  286.  
  287. */
  288.  
  289. LONG
  290. CommandAbout(argArray, apiMsg)
  291.  
  292. ULONG  *argArray;
  293. struct APIMessage *apiMsg;
  294. {
  295.     struct EasyStruct about = {sizeof(struct EasyStruct), 0, "Info", "Just some API client example code", "OK" };
  296.  
  297.     EasyRequestArgs(apiMsg->api_WinInfo->Window, &about, NULL, NULL);
  298.  
  299.     return(RC_OK);
  300. }
  301.  
  302.  
  303. ///
  304. /// "ARexx"
  305.  
  306. /* ---------------------------------- SendRexxCommand -------------------------
  307.  
  308.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  309.  
  310.  Envoyer une commande ARexx et attendre une réponse. Retourne un pointeur sur le
  311.  résultat ou NULL.
  312.  
  313. */
  314.  
  315. ULONG *
  316. SendRexxCommand(port, cmd, replyPort, buffer)
  317.  
  318. char   *cmd, *port, *buffer;
  319. struct MsgPort *replyPort;
  320. {
  321.     struct MsgPort *rexxport;
  322.  
  323.     Forbid();
  324.  
  325.     if (rexxport = FindPort(port)) {
  326.  
  327.         struct RexxMsg *rexxMsg, *answer;
  328.  
  329.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  330.  
  331.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  332.  
  333.                 static ULONG result;
  334.  
  335.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  336.  
  337.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  338.  
  339.                 do {
  340.                     
  341.                     WaitPort(replyPort);
  342.  
  343.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  344.                         result = answer->rm_Result1;
  345.  
  346.                 } while (!answer);
  347.  
  348.                 Permit();
  349.  
  350.                 if (answer->rm_Result1 == RC_OK) {
  351.  
  352.                     if (answer->rm_Result2) {
  353.  
  354.                         if (buffer)
  355.                             strcpy(buffer, (char *)answer->rm_Result2);
  356.  
  357.                         DeleteArgstring((char *)answer->rm_Result2);
  358.                     }
  359.                 }
  360.  
  361.                 DeleteArgstring((char *)ARG0(answer));
  362.  
  363.                 DeleteRexxMsg(answer);
  364.  
  365.                 return(&result);
  366.             }
  367.         }
  368.     }
  369.  
  370.     Permit();
  371.  
  372.     return(NULL);
  373. }
  374.  
  375. ///
  376.